package com.alex.goods.service.impl;

import com.alex.core.entity.ApiResponse;
import com.alex.core.entity.PageInfo;
import com.alex.core.enums.ApiResponseEnum;
import com.alex.core.util.ApiResponseUtil;
import com.alex.goods.entity.dos.Category;
import com.alex.goods.entity.dto.CategoryQueryDTO;
import com.alex.goods.entity.dto.CategorySaveDTO;
import com.alex.goods.entity.dto.CategoryUpdateDTO;
import com.alex.goods.entity.vo.CategoryQueryVO;
import com.alex.goods.mapper.CategoryMapper;
import com.alex.goods.service.CategoryService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.text.NumberFormat;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author cb
 * @date 2019/11/13 11:35
 */
@Service
@Slf4j
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
    /**
     * 每级编码长度
     */
    private static final Integer CODE_BIT_PER_LEVEL = 2;

    @Override
    public ApiResponse save(CategorySaveDTO request) {
        Category parent = null;
        if (request.getParentId() != null && request.getParentId() != 0) {
            parent = getById(request.getParentId());
            if (Objects.isNull(parent)) {
                return ApiResponseUtil.failure(ApiResponseEnum.CATEGORY_PARENT_ID_INVALID);
            }
        }
        Category category = new Category();
        BeanUtils.copyProperties(request, category);
        // 设置分类编码
        if (Objects.nonNull(parent)) {
            // 当前父分类最大编码
            category.setCode(getCode(parent.getId(), parent.getCode()));
        } else {
            // 顶级下获取最大编码
            category.setCode(getCode(0, ""));
        }
        save(category);
        return ApiResponseUtil.success(category);
    }

    /**
     * 新增时获取编码
     *
     * @param parentId   上级ID，顶级为0
     * @param parentCode 上级code，顶级为""
     * @return
     */
    private String getCode(Integer parentId, String parentCode) {
        Category maxCodeCategory = getOne(new QueryWrapper<Category>().eq("parent_id", parentId).orderByDesc("code"));
        log.info("父级下最大code分类===================>{}", maxCodeCategory);
        String code;
        if (Objects.nonNull(maxCodeCategory)) {
            String maxCode = maxCodeCategory.getCode();
            NumberFormat format = NumberFormat.getInstance();
            format.setMaximumIntegerDigits(CODE_BIT_PER_LEVEL);
            format.setMinimumIntegerDigits(CODE_BIT_PER_LEVEL);
            code = maxCode.substring(0, maxCode.length() - CODE_BIT_PER_LEVEL) + format.format(Integer.parseInt(maxCode.substring(maxCode.length() - CODE_BIT_PER_LEVEL)) + 1);
        } else {
            code = String.format("%s00", parentCode);
        }
        log.info("设置的编码{}", code);
        return code;
    }

    @Override
    public ApiResponse remove(Integer id) {
        int count = count(new QueryWrapper<Category>().eq("parent_id", id));
        if (count > 0) {
            return ApiResponseUtil.failure(ApiResponseEnum.CATEGORY_HAS_CHILDREN);
        }
        Category category = getById(id);
        if (Objects.nonNull(category)) {
            removeById(id);
        }
        return ApiResponseUtil.success("删除成功");
    }

    @Override
    public ApiResponse get(Integer id) {
        Category category = getById(id);
        if (Objects.isNull(category)) {
            return ApiResponseUtil.failure(ApiResponseEnum.CATEGORY_CAN_NOT_FIND_BY_ID);
        }
        Category vo = new Category();
        vo.setId(category.getId());
        vo.setName(category.getName());
        vo.setParentId(category.getParentId());
        return ApiResponseUtil.success(vo);
    }

    @Override
    public ApiResponse update(CategoryUpdateDTO request) {
        Category parent = null;
        if (request.getParentId() != null && request.getParentId() != 0) {
            parent = getById(request.getParentId());
            if (Objects.isNull(parent)) {
                return ApiResponseUtil.failure(ApiResponseEnum.CATEGORY_PARENT_ID_INVALID);
            }
        }
        Category original = getById(request.getId());
        if (Objects.isNull(original)) {
            return ApiResponseUtil.failure(ApiResponseEnum.CATEGORY_CAN_NOT_FIND_BY_ID);
        }
        Category category = new Category();
        BeanUtils.copyProperties(request, category);
        if (!original.getParentId().equals(request.getParentId())) {
            // 设置分类编码
            if (Objects.nonNull(parent)) {
                // 当前父分类最大编码
                category.setCode(getCode(parent.getId(), parent.getCode()));
            } else {
                // 顶级下获取最大编码
                category.setCode(getCode(0, ""));
            }
        }
        // 只允许修改为同级
        if (original.getCode().length() != category.getCode().length()) {
            return ApiResponseUtil.failure(ApiResponseEnum.CATEGORY_CAN_NOT_UPDATE_LEVEL_NOT_EQUAL);
        }
        updateById(category);
        return ApiResponseUtil.success(category);
    }

    @Override
    public ApiResponse page(CategoryQueryDTO request) {
        Page<Category> page = new Page<>(request.getPageNo(), request.getPageSize(), true);
        page(page, new QueryWrapper<Category>()
                .like(StringUtils.isNotBlank(request.getName()), "name", request.getName())
                .eq(Objects.nonNull(request.getParentId()), "parent_id", request.getParentId())
                .orderByDesc("gmt_create"));
        List<Category> records = page.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return ApiResponseUtil.success(PageInfo.builder().total(0).records(Lists.newArrayList()).build());
        }

        List<Category> parentList = (List<Category>) listByIds(records.stream().map(Category::getParentId).collect(Collectors.toSet()));
        List<CategoryQueryVO> voList = records.stream().map(e -> {
            CategoryQueryVO vo = new CategoryQueryVO();
            BeanUtils.copyProperties(e, vo);
            Optional<Category> parentOptional = parentList.stream().filter(obj -> e.getParentId().equals(obj.getId())).findFirst();
            if (parentOptional.isPresent()) {
                vo.setParentName(parentOptional.get().getName());
            }
            return vo;
        }).collect(Collectors.toList());
        return ApiResponseUtil.success(new PageInfo(page.getTotal(), voList));
    }

}
